package com.tongji.housediy.view.component3D
{
	import alternativa.engine3d.containers.ConflictContainer;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.Clipping;
	import alternativa.engine3d.core.Debug;
	import alternativa.engine3d.core.MipMapping;
	import alternativa.engine3d.core.MouseEvent3D;
	import alternativa.engine3d.core.Object3D;
	import alternativa.engine3d.core.Sorting;
	import alternativa.engine3d.core.Vertex;
	import alternativa.engine3d.core.View;
	import alternativa.engine3d.lights.AmbientLight;
	import alternativa.engine3d.lights.DirectionalLight;
	import alternativa.engine3d.loaders.MaterialLoader;
	import alternativa.engine3d.loaders.ParserCollada;
	import alternativa.engine3d.loaders.events.LoaderEvent;
	import alternativa.engine3d.materials.FillMaterial;
	import alternativa.engine3d.materials.FlatShadingMaterial;
	import alternativa.engine3d.materials.Material;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.materials.VertexLightMaterial;
	import alternativa.engine3d.objects.BSP;
	import alternativa.engine3d.objects.Mesh;
	
	import caurina.transitions.Tweener;
	
	import com.tongji.housediy.events.commonEvent.ExchangeDataEvent;
	import com.tongji.housediy.utils.ConstVariableInventory;
	import com.tongji.housediy.view.components.Furniture;
	import com.tongji.housediy.view.components.IndependentFloor;
	import com.tongji.housediy.view.components.RoomBorder;
	import com.tongji.housediy.view.components.RoomFloor;
	import com.tongji.housediy.vo.Goods;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.GradientType;
	import flash.display.Loader;
	import flash.display.Scene;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.ui.Keyboard;
	
	import mx.core.UIComponent;
	import mx.utils.object_proxy;
	
	import spark.primitives.Rect;
	
	[SWF(backgroundColor="#FFFFFF", frameRate="60", width="800", height="600")]
	public class CreateRoom3D extends UIComponent {
		
		public var camera:Camera3D;
		private var fcamera:Camera3D;
		
		private var container:ConflictContainer = new ConflictContainer();
		
		private var wallMaterial:WallMaterial;
		private var ceilingMaterial:CeilingMaterial;
		private var floorMaterial:TextureMaterial;
		private var doorMaterial:TextureMaterial;
		private var windowMaterial:TextureMaterial;
		private var outMaterial:TextureMaterial;
		
		private var dae:Object3D;
		private var i:int;
		
		private var data:Vector.<Number> = new Vector.<Number>;
		private var curveVector:Vector.<int> = new Vector.<int>;
		private var cameraPosition:Point;
		private var cameraRotation:Number;
		
		//移动
		private var keyRight:Boolean;
		private var keyLeft:Boolean;
		private var keyForward:Boolean;
		private var keyBackward:Boolean;
		private var backward:Point = new Point();
		private var forward:Point = new Point();
		private var leftMove:Point = new Point();
		private var rightMove:Point = new Point();
		private var speed:Number = 5;
		private var moveable:Boolean = true;
		
		//旋转
		private var rotate:Boolean = false;
		private var lastMouseX:Number = 0;
		private var lastMouseY:Number = 0;
		private var lastRotationZ:Number = 0;
		private var lastRotationX:Number = 0;
		private var nextRotationZ:Number = 0;
		private var nextRotationX:Number = -100 * Math.PI / 180;
		private var nowRotationZ:Number = 0;
		private var nowRotationX:Number = -100 * Math.PI / 180;
		
		//碰撞检测
		private var start:Point = new Point();
		private var end:Point = new Point();
		private var vertexPosition2D:Vector.<Number> //储存外墙的点2D坐标,按X,Y,X,Y排序
		public var outsidePosition2D:Vector.<Number> = new Vector.<Number>; //储存所有外墙的点2D坐标,按X,Y,X,Y排序
		public var insidePosition2D:Vector.<Number> = new Vector.<Number>; //储存所有内墙的点2D坐标,按X,Y,X,Y排序
		
		//墙面选择
		public var selectedWall:Wall;
		
		//切换视角
		private var eightViewAngel:Number = 0;
		private var eightViewDistance:Number = 800;
		public var distanceScale:Number = 1;
		
		private var sixViewAngel:Number = 0;
		private var sixViewDistance:Number = 800;
		
		public var direction:Number = 0;
		public var moveSpeed:Number = 0;
		public var rotateSpeed:Number = 0;
		public var inStage:Boolean = false;
		public var state:String = "eightView"; // eightView, sixView, freeView
		
		public var roomCount:int = 0;
		
		//光照
		private var directionalLight:DirectionalLight = new DirectionalLight(0xFFFFFF);
		private var ambientLight:AmbientLight = new AmbientLight(0x333333);
		
		public function CreateRoom3D()
		{
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		public function stageResizeHandler(event:Event = null):void
		{
			camera.view.width = this.parent.width;
			camera.view.height = this.parent.height;
			
			fcamera.view.width = this.parent.width;
			fcamera.view.height = this.parent.height;
		}
		
		public function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.MEDIUM;
			
			camera = new Camera3D();
			camera.view = new View(this.parent.width, this.parent.height);
			camera.view.hideLogo();
			camera.rotationX = -100 * Math.PI / 180;
			camera.view.doubleClickEnabled = true;
			fcamera = new Camera3D();
			fcamera.view = new View(this.parent.width, this.parent.height);
			fcamera.view.hideLogo();
			fcamera.scaleZ = -1;
			addChild(fcamera.view);
			addChild(camera.view);
			
			container.resolveByAABB = true;
			container.resolveByOOBB = true;
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHand);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHand);
			this.parent.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			this.parent.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			
			stage.addEventListener(Event.RESIZE, stageResizeHandler);
			
			inStage = true;
			initEightView();
		}
		
		public function addRoom(data2D:Vector.<Number>, curveVector:Vector.<int>, initialWallVector:Vector.<Number>, borderChildVector:Vector.<Vector.<Number>>, relatedFloor:RoomFloor, roomHeight:int, doorWindowRelatedMap:Vector.<BitmapData>, borderVector:Vector.<RoomBorder>):void
		{
			var data3D:Vector.<Number> = new Vector.<Number>;
			var datalength:int = data2D.length;
			for (i = 0; i < datalength - 2; i++)
			{
				if (i%2 == 0)
					data3D[i] = data2D[i];
				else
					data3D[i] = -data2D[i];
			}
			
			this.data = data3D;
			this.curveVector = curveVector;
			
			//初始化
			vertexPosition2D = new Vector.<Number>;
			//wallMaterial = new WallMaterial(500, roomHeight, new BitmapData(2,2,false,0xffffff), new BitmapData(2,2,false,0x999999));
			ceilingMaterial = new CeilingMaterial(500, 500, new BitmapData(2,2,false,0xffffff));
			outMaterial = new TextureMaterial(new BitmapData(1,1,true,0x66ffffff));
			
			var dataLength:int = data.length;
			var index1:int;
			var index2:int;
			var index3:int;
			var wallCount:int = 0;
			var doorWindowRelatedMapCount:int = 0;
			for (var count:int = 0; count < dataLength;)
			{
				if (curveVector.indexOf(count / 2) != -1)
				{
					index1 = count;
					index2 = count + 2;
					index3 = count + 4;
					if (index3 >= dataLength)
						index3 -= dataLength;
					//曲面墙
					wallMaterial = new WallMaterial(Math.sqrt((data[index1] - data[index3]) * (data[index1] - data[index3]) + (data[index1 + 1] - data[index3 + 1]) * (data[index1 + 1] - data[index3 + 1])), roomHeight, borderVector[wallCount].wallMap ,borderVector[wallCount].skirtingMap);

					var curveWall:CurvedWall = new CurvedWall(data[index1], data[index1 + 1], data[index2], data[index2 + 1], data[index3], data[index3 + 1], roomHeight, wallMaterial);
					container.addChild(curveWall);
					
					curveWall.roomCount = roomCount;
					curveWall.wallCount = wallCount;
					curveWall.wallBitmap = borderVector[wallCount].wallMap;
					curveWall.underBitmap = borderVector[wallCount].skirtingMap;
					
					curveWall.doubleClickEnabled = true;
					curveWall.addEventListener(MouseEvent3D.DOUBLE_CLICK, changeMaterial);
					var curveWallLength:int = curveWall.vertices.length / 4;
					for (var v:int = 0; v < curveWallLength - 1; v++)
					{
						vertexPosition2D.push(curveWall.vertices[4 * v].x, curveWall.vertices[4 * v].y);
						var outWall:OutWall = new OutWall(curveWall.vertices[4 * v].x, curveWall.vertices[4 * v].y, curveWall.vertices[4 * v + 4].x, curveWall.vertices[4 * v + 4].y, roomHeight, outMaterial, new Vector.<Number>);
						container.addChild(outWall);
						outsidePosition2D.push(curveWall.vertices[4 * v].x, curveWall.vertices[4 * v].y, curveWall.vertices[4 * v + 4].x, curveWall.vertices[4 * v + 4].y);
					}
					count += 4;
					wallCount++;
				}
				else
				{
					index1 = count;
					index2 = count + 2;
					if (index2 >= dataLength)
						index2 -= dataLength;
					//直墙
					wallMaterial = new WallMaterial(Math.sqrt((data[index1] - data[index2]) * (data[index1] - data[index2]) + (data[index1 + 1] - data[index2 + 1]) * (data[index1 + 1] - data[index2 + 1])), roomHeight, borderVector[wallCount].wallMap ,borderVector[wallCount].skirtingMap);
					
					var straightWall:StraightWall = new StraightWall(data[index1], data[index1 + 1], data[index2], data[index2 + 1], roomHeight, wallMaterial, borderChildVector[wallCount]);
					container.addChild(straightWall);
					
					straightWall.roomCount = roomCount;
					straightWall.wallCount = wallCount;
					straightWall.wallBitmap = borderVector[wallCount].wallMap;
					straightWall.underBitmap = borderVector[wallCount].skirtingMap;
					
					straightWall.doubleClickEnabled = true;
					straightWall.addEventListener(MouseEvent3D.DOUBLE_CLICK, changeMaterial);
					outWall = new OutWall(data[index1], data[index1 + 1], data[index2], data[index2 + 1], roomHeight, outMaterial, borderChildVector[wallCount]);
					container.addChild(outWall);
					//门窗
					var borderChild:Vector.<Number> = borderChildVector[wallCount];
					for (i = 0; i<borderChild.length / 8; i++)
					{
						switch (borderChild[8 * i + 6])
						{
							case 0:
							{
								doorMaterial = new TextureMaterial(doorWindowRelatedMap[doorWindowRelatedMapCount]);
								var door:Door = new Door(borderChild[8 * i + 0], borderChild[8 * i + 1], borderChild[8 * i + 2],  borderChild[8 * i + 3], borderChild[8 * i + 5], doorMaterial);
								door.isTwoSide = borderChild[8 * i + 7];
								container.addChild(door);
								door.doubleClickEnabled = true;
								door.addEventListener(MouseEvent3D.DOUBLE_CLICK, changePosition);
								var outDoor:Door = new Door(borderChild[8 * i + 2], borderChild[8 * i + 3], borderChild[8 * i + 0],  borderChild[8 * i + 1], borderChild[8 * i + 5], doorMaterial);
								container.addChild(outDoor);
								outDoor.alpha = 0.5;
								outsidePosition2D.push(borderChild[8 * i + 0], borderChild[8 * i + 1], borderChild[8 * i + 2], borderChild[8 * i + 3]);
								doorWindowRelatedMapCount++;
								break;
							}
							case 1:
							{
								windowMaterial = new TextureMaterial(doorWindowRelatedMap[doorWindowRelatedMapCount]);
								var window:Window = new Window(borderChild[8 * i + 0], borderChild[8 * i + 1], borderChild[8 * i + 2], borderChild[8 * i + 3], borderChild[8 * i + 4], borderChild[8 * i + 5], windowMaterial);
								container.addChild(window);
								var outWindow:Window = new Window(borderChild[8 * i + 2], borderChild[8 * i + 3], borderChild[8 * i + 0],  borderChild[8 * i + 1], borderChild[8 * i + 4], borderChild[8 * i + 5], windowMaterial);
								container.addChild(outWindow);
								outWindow.alpha = 0.5;
								outsidePosition2D.push(borderChild[8 * i + 0], borderChild[8 * i + 1], borderChild[8 * i + 2], borderChild[8 * i + 3]);
								doorWindowRelatedMapCount++;
								break;
							}
						}
					}
					outsidePosition2D.push(data[index1], data[index1 + 1]);
					if (borderChild.length > 0)
					{
						outsidePosition2D.push(borderChild[0], borderChild[1]);
						for (i = 1; i < borderChild.length / 8; i++)
						{
							outsidePosition2D.push(borderChild[8 * i - 6], borderChild[8 * i - 5], borderChild[8 * i + 0], borderChild[8 * i + 1]);
						}
						outsidePosition2D.push(borderChild[8 * i - 6], borderChild[8 * i - 5]);
					}
					outsidePosition2D.push(data[index2], data[index2 + 1]);
						
					vertexPosition2D.push(straightWall.vertices[0].x, straightWall.vertices[0].y);
					for (i = 0; i < borderChild.length / 8; i++)
					{
						vertexPosition2D.push(borderChild[8 * i + 0], borderChild[8 * i + 1], borderChild[8 * i + 2], borderChild[8 * i + 3]);
					}
					count += 2;
					wallCount++;
				}
			}
			
			//构建内墙
			var insideWall:Vector.<Number> = new Vector.<Number>;
			var initialWallLength:int = initialWallVector.length;
			for (i=0;i<initialWallLength;i++)
			{
				if (i%2 == 0)
					insideWall[i] = initialWallVector[i];
				else
					insideWall[i] = -initialWallVector[i];
			}
			for (count = 0; count < initialWallLength;count += 4)
			{
				index1 = count;
				index2 = count + 2;
				var straightWall1:StraightWall = new StraightWall(insideWall[index1], insideWall[index1 + 1], insideWall[index2], insideWall[index2 + 1], roomHeight, wallMaterial, new Vector.<Number>);
				container.addChild(straightWall1);
				straightWall1.doubleClickEnabled = true;
				straightWall1.addEventListener(MouseEvent3D.DOUBLE_CLICK, changeMaterial);
				var straightWall2:StraightWall = new StraightWall(insideWall[index2], insideWall[index2 + 1], insideWall[index1], insideWall[index1 + 1], roomHeight, wallMaterial, new Vector.<Number>);
				container.addChild(straightWall2);
				straightWall2.doubleClickEnabled = true;
				straightWall2.addEventListener(MouseEvent3D.DOUBLE_CLICK, changeMaterial);
				insidePosition2D.push(straightWall1.vertices[0].x, straightWall1.vertices[0].y);
				insidePosition2D.push(straightWall2.vertices[0].x, straightWall2.vertices[0].y);
			}
			
			//用于计算uv的数据
			var maxX:Number = vertexPosition2D[0];
			var minX:Number = vertexPosition2D[0];
			var maxY:Number = vertexPosition2D[1];
			var minY:Number = vertexPosition2D[1];
			var vertexLength:int = vertexPosition2D.length / 2;
			for (i = 1; i < vertexLength; i++)
			{
				if (vertexPosition2D[2 * i] > maxX)
					maxX = vertexPosition2D[2 * i];
				if (vertexPosition2D[2 * i] < minX)
					minX = vertexPosition2D[2 * i];		
				if (vertexPosition2D[2 * i + 1] > maxY)
					maxY = vertexPosition2D[2 * i + 1];
				if (vertexPosition2D[2 * i + 1] < minY)
					minY = vertexPosition2D[2 * i + 1];		
			}
			var distanceX:Number = maxX - minX;
			var distanceY:Number = maxY - minY;
			
			var floor:Mesh = new Mesh();
			var ceiling:Mesh = new Mesh();
			
			//地板材料
			var texture:BitmapData = relatedFloor.materialBitmapData;
			var rec:Rectangle = new Rectangle(0, 0, texture.width, texture.height)
			var point:Point = new Point();
			var floorBitmap:BitmapData = new BitmapData(distanceX, distanceY);
			var shape:Shape = new Shape();
			for (var m:Number = 0; m < distanceX / rec.width; m++) 
			{
				for(var n:Number = 0; n < distanceY / rec.height; n++)
				{
					point.x = rec.width * m;
					point.y = rec.height * n;
					floorBitmap.copyPixels(texture, rec, point);
				}
			}
			for (i = 0; i<relatedFloor.numChildren; i++)
			{
				if (relatedFloor.getChildAt(i) is IndependentFloor)
				{
					var o:IndependentFloor = relatedFloor.getChildAt(i) as IndependentFloor;
					shape.graphics.clear();
					shape.graphics.beginBitmapFill(o.roomFloor.materialBitmapData);
					shape.graphics.moveTo(o.x + o.exchangeData[0] - minX, o.y + o.exchangeData[1] + maxY);
					for (var j:int = 1; j<o.exchangeData.length / 2; j++)
					{
						shape.graphics.lineTo(o.x + o.exchangeData[2 * j] - minX, o.y + o.exchangeData[2 * j + 1] + maxY);
					}
					shape.graphics.endFill();
					floorBitmap.draw(shape);
				}
			}
			floorMaterial = new TextureMaterial();
			floorMaterial.texture = floorBitmap;
			
			//地板和天花板
			var floorVertex:Vector.<Vertex> = new Vector.<Vertex>;
			var ceilingVertex:Vector.<Vertex> = new Vector.<Vertex>;
			for (i = 0; i < vertexLength; i++)
			{
				var floorX:Number = vertexPosition2D[2 * i];
				var floorY:Number = vertexPosition2D[2 * i + 1];
				var floorU:Number = (floorX - minX) / distanceX;
				var floorV:Number = (floorY - minY) / distanceY;
				var vertex1:Vertex = floor.addVertex(floorX, floorY, 0, floorU, 1 - floorV);
				var vertex2:Vertex = ceiling.addVertex(floorX, floorY, roomHeight, floorU, 1 - floorV);
				floorVertex.push(vertex1);
				ceilingVertex.push(vertex2);
			}
			
			
			var removeable:Boolean;
			for (i = 1; i < floorVertex.length - 2; i++)
			{
				if (isClockwise(floorVertex[i - 1].x, floorVertex[i - 1].y, floorVertex[i].x, floorVertex[i].y, floorVertex[i + 1].x, floorVertex[i + 1].y))
				{
					removeable = true;
					if (floorVertex.length > 4)
					{
						for (var k:int = i + 2; k != i - 2 && k != i - 2 + floorVertex.length; k++)
						{
							if (k >= floorVertex.length)
								k -= floorVertex.length;
							var aaa:int = k;
							if (k + 1 >= floorVertex.length)
								k -= floorVertex.length;
							var bbb:int = k + 1;
							if (isIntersect(new Point(floorVertex[i - 1].x, floorVertex[i - 1].y), new Point(floorVertex[i + 1].x, floorVertex[i + 1].y), new Point(floorVertex[aaa].x, floorVertex[aaa].y), new Point(floorVertex[bbb].x, floorVertex[bbb].y)))
								removeable = false;
						}
					}
					else
					{
						var ccc:int = i + 1;
						if (ccc >= floorVertex.length)
							ccc -= floorVertex.length;
						var ddd:int = i + 2;
						if (ddd >= floorVertex.length)
							ddd -= floorVertex.length;
						var eee:int = i + 3;
						if (eee >= floorVertex.length)
							eee -= floorVertex.length;
						if (!isClockwise(floorVertex[ccc].x, floorVertex[ccc].y, floorVertex[ddd].x, floorVertex[ddd].y, floorVertex[eee].x, floorVertex[eee].y))
						{
							removeable = false;
						}
					}
					if (removeable)
					{
						var tempVertex:Vector.<Vertex> = new Vector.<Vertex>;
						tempVertex.push(floorVertex[i + 1],floorVertex[i],floorVertex[i - 1]);
						floor.addFace(tempVertex, floorMaterial);
						floorVertex.splice(i,1);
						tempVertex = new Vector.<Vertex>;
						tempVertex.push(ceilingVertex[i - 1],ceilingVertex[i],ceilingVertex[i + 1]);
						ceiling.addFace(tempVertex, ceilingMaterial);
						ceilingVertex.splice(i,1);
						i = 0;
					}
				}
			}
			floor.addFace(floorVertex.reverse(), floorMaterial);
			ceiling.addFace(ceilingVertex, ceilingMaterial);
			
			
			floor.calculateFacesNormals();
			container.addChild(floor);
			floor.alpha = 0.8;
			
			ceiling.calculateFacesNormals();
			container.addChild(ceiling);
			
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			
			for (i = 0; i<relatedFloor.numChildren; i++)
			{
				if (relatedFloor.getChildAt(i) is Furniture)
				{
					var furniture:Furniture = relatedFloor.getChildAt(i) as Furniture;
					var rectangle:Rectangle = furniture.getRect(furniture.parent.parent.parent);
					loadModel(rectangle.x + rectangle.width / 2, -rectangle.y - rectangle.height / 2, furniture.modelZPosition, -furniture.rotation, furniture.modelSrc, furniture.mapPicSrc);
				}
			}
			
		}
		
		public function setCameraPosition(cameraPosition:Point, cameraRotation:Number):void
		{
			this.cameraPosition = cameraPosition;
			this.cameraRotation = cameraRotation;
			state = "freeView";
			camera.view.x = 0;
			camera.view.y = 0;
			
			nextRotationZ = camera.rotationZ;
			nextRotationX = - Math.PI / 2;
			Tweener.addTween(camera, {x:cameraPosition.x,
				y:-cameraPosition.y,
				z:140,
				rotationX: - Math.PI / 2,
				rotationZ: nextRotationZ,
				time:1} )
			
			
			fcamera.view.visible = true;
			//camera.debug = true;
			//addChild(camera.diagram);
		}
		
		public function removeRoom():void
		{
			state = "eightView";
			container = new ConflictContainer();
			vertexPosition2D = new Vector.<Number>;
			insidePosition2D = new Vector.<Number>;
			removeEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		public function onEnterFrame(e:Event = null):void 
		{		
			if (state == "freeView")
			{
				if(keyForward)
				{
					forward.x = camera.x - Math.sin(camera.rotationZ) * speed;
					forward.y = camera.y + Math.cos(camera.rotationZ) * speed;
					moveable = CameraControl.collisionDetect(camera, forward, outsidePosition2D, insidePosition2D);
					if (moveable)
					{
						camera.x = forward.x;
						camera.y = forward.y;
					}
				}
				
				if(keyBackward)
				{
					backward.x = camera.x + Math.sin(camera.rotationZ) * speed;
					backward.y = camera.y - Math.cos(camera.rotationZ) * speed;
					moveable = CameraControl.collisionDetect(camera, backward, outsidePosition2D, insidePosition2D);
					if (moveable)
					{
						camera.x = backward.x;
						camera.y = backward.y;
					}
				}
				
				if(keyLeft)
				{
					leftMove.x = camera.x - Math.cos(camera.rotationZ) * speed;
					leftMove.y = camera.y - Math.sin(camera.rotationZ) * speed;
					moveable = CameraControl.collisionDetect(camera, leftMove, outsidePosition2D, insidePosition2D);
					if (moveable)
					{
						camera.x = leftMove.x;
						camera.y = leftMove.y;
					}
				}
				
				if(keyRight)
				{
					rightMove.x = camera.x + Math.cos(camera.rotationZ) * speed;
					rightMove.y = camera.y + Math.sin(camera.rotationZ) * speed;
					moveable = CameraControl.collisionDetect(camera, rightMove, outsidePosition2D, insidePosition2D);
					if (moveable)
					{
						camera.x = rightMove.x;
						camera.y = rightMove.y;
					}
				}
				
				if (rotate)
				{
					nextRotationZ = lastRotationZ - 0.005 * (this.mouseX - lastMouseX);
					nextRotationX = lastRotationX - 0.005 * (this.mouseY - lastMouseY);
					if (nextRotationX < -120 * Math.PI / 180)
						nextRotationX = -120 * Math.PI / 180;
					if (nextRotationX > -60 * Math.PI / 180)
						nextRotationX = -60 * Math.PI / 180;
				}
				
				camera.rotationZ += (nextRotationZ - nowRotationZ) * 0.1;
				camera.rotationX += (nextRotationX - nowRotationX) * 0.1;
				nowRotationZ = camera.rotationZ;
				nowRotationX = camera.rotationX;
				
				this.dispatchEvent(new ExchangeDataEvent(ExchangeDataEvent.UPDATE_MAP_POSITION_ROTAION, new Point(camera.x, camera.y), camera.rotationZ * 180 / Math.PI));
				
				fcamera.rotationX = -camera.rotationX;
				fcamera.rotationZ = camera.rotationZ;
				fcamera.x = camera.x;
				fcamera.y = camera.y ;
				fcamera.z = -camera.z;
				fcamera.fov = camera.fov;
				
				fcamera.render();
			}
			
			if (state == "eightView")
			{
				camera.x -= Math.sin(camera.rotationZ + direction * Math.PI / 2) * moveSpeed;
				camera.y += Math.cos(camera.rotationZ + direction * Math.PI / 2) * moveSpeed;
				camera.rotationX += rotateSpeed * Math.PI / 180;
				if (camera.rotationX > - Math.PI / 2) 
					camera.rotationX = - Math.PI / 2;
				if (camera.rotationX < - Math.PI) 
					camera.rotationX = - Math.PI;
				
				if (rotate)
				{
					camera.view.x += 1 * (this.mouseX - lastMouseX);
					camera.view.y += 1 * (this.mouseY - lastMouseY);
					lastMouseX = this.mouseX;
					lastMouseY = this.mouseY;
				}
				
			}
			directionalLight.rotationZ -= 0.02;
			camera.render();
		}
		
		public function initEightView(e:Event = null):void
		{
			
			eightViewAngel = Math.PI / 4;
			container.addChild(camera);
			container.addChild(fcamera);
			fcamera.view.visible = false;
			camera.render();
			container.removeChild(directionalLight);
			container.removeChild(ambientLight);
			container.calculateBounds();
			container.addChild(ambientLight);
			container.addChild(directionalLight);
			eightViewDistance = container.boundMaxX - container.boundMinX > container.boundMaxY - container.boundMinY ? distanceScale * ConstVariableInventory.EIGHT_VIEW_SCALE * (container.boundMaxX - container.boundMinX) : distanceScale * ConstVariableInventory.EIGHT_VIEW_SCALE * (container.boundMaxY - container.boundMinY);
			Tweener.addTween(camera, {x: (container.boundMaxX + container.boundMinX) / 2 + eightViewDistance * Math.sin(eightViewAngel),
				y: (container.boundMaxY + container.boundMinY) / 2 - eightViewDistance * Math.cos(eightViewAngel),
				z: eightViewDistance,
				rotationX: -Math.PI * 3 / 4,
				rotationZ: eightViewAngel,
				time: 1});
		}
		
		public function changeEightView(change:int):void
		{
			this.state = "eightView";
			eightViewAngel += change * Math.PI / 4;
			fcamera.view.visible = false;
			container.removeChild(directionalLight);
			container.removeChild(ambientLight);
			container.calculateBounds();
			container.addChild(ambientLight);
			container.addChild(directionalLight);
			eightViewDistance = container.boundMaxX - container.boundMinX > container.boundMaxY - container.boundMinY ? distanceScale * ConstVariableInventory.EIGHT_VIEW_SCALE * (container.boundMaxX - container.boundMinX) : distanceScale * ConstVariableInventory.EIGHT_VIEW_SCALE * (container.boundMaxY - container.boundMinY);
			Tweener.addTween(camera, {x:(container.boundMaxX + container.boundMinX) / 2 + eightViewDistance * Math.sin(eightViewAngel),
			y:(container.boundMaxY + container.boundMinY) / 2 - eightViewDistance * Math.cos(eightViewAngel),
			z:eightViewDistance,
			rotationX: -Math.PI * 3 / 4,
			rotationZ: eightViewAngel,
			time:0.5} )
		}
		
		public function changeSixView(view:int):void
		{
			this.state = "sixView";
			fcamera.view.visible = false;
			container.removeChild(directionalLight);
			container.removeChild(ambientLight);
			container.calculateBounds();
			container.addChild(ambientLight);
			container.addChild(directionalLight);
			sixViewDistance = container.boundMaxX - container.boundMinX > container.boundMaxY - container.boundMinY ? ConstVariableInventory.SIX_VIEW_SCALE * (container.boundMaxX - container.boundMinX) : ConstVariableInventory.EIGHT_VIEW_SCALE * (container.boundMaxY - container.boundMinY);
			if (view > 0)
			{
				sixViewAngel = Math.PI / 2 * view;
				camera.x = (container.boundMaxX + container.boundMinX) / 2 + sixViewDistance * Math.sin(sixViewAngel);
				camera.y = (container.boundMaxY + container.boundMinY) / 2 - sixViewDistance * Math.cos(sixViewAngel);
				camera.z = container.boundMaxZ / 2;
				camera.rotationX = -Math.PI / 2;
				camera.rotationZ = sixViewAngel;
			}
			else if (view < 0 )
			{
				camera.x = (container.boundMaxX + container.boundMinX) / 2
				camera.y = (container.boundMaxY + container.boundMinY) / 2
				camera.z = sixViewDistance * 1.5;
				camera.rotationX = -Math.PI;
				camera.rotationZ = 0;
			}
			else
			{
				camera.x = (container.boundMaxX + container.boundMinX) / 2
				camera.y = (container.boundMaxY + container.boundMinY) / 2
				camera.z = 3;
				camera.rotationX = 0;
				camera.rotationZ = 0;
			}
		}
		
		private function onMouseDown(event:MouseEvent):void
		{
			stage.focus = this;
			lastRotationZ = camera.rotationZ;
			lastRotationX = camera.rotationX;
			lastMouseX = this.mouseX;
			lastMouseY = this.mouseY;
			rotate = true;
		}
		
		private function onMouseUp(event:MouseEvent = null):void
		{
			rotate = false;
		}
		
		private function keyDownHand(e:KeyboardEvent):void
		{	
			switch( e.keyCode )
			{
				case "W".charCodeAt():
				case Keyboard.UP:
					keyForward = true;
					break;
				case "S".charCodeAt():
				case Keyboard.DOWN:
					keyBackward = true;
					break;
				case "A".charCodeAt():
				case Keyboard.LEFT:
					keyLeft = true;
					break;
				case "D".charCodeAt():
				case Keyboard.RIGHT:
					keyRight = true;
					break;
				case 81: // Q
					if (stage.quality == "HIGH") {
						stage.quality = StageQuality.LOW;
					} else {
						stage.quality = StageQuality.HIGH;
					} 
					break;
				case Keyboard.TAB:
					camera.debug = !camera.debug;
					break;
				case Keyboard.ENTER:
					break;
			}
		}
		
		private function keyUpHand(e:KeyboardEvent):void
		{
			switch(e.keyCode)
			{
				case "W".charCodeAt():
				case Keyboard.UP:
					keyForward = false;
					break;
				case "S".charCodeAt():
				case Keyboard.DOWN:
					keyBackward = false;
					break;
				case "A".charCodeAt():
				case Keyboard.LEFT:
					keyLeft = false;
					break;
				case "D".charCodeAt():
				case Keyboard.RIGHT:
					keyRight = false;
					break;
			}
		}
		
		public function resetSelectedBitmap(wallBitmap:BitmapData, underBitmap:BitmapData):void
		{	
			if (selectedWall != null)
			{
				var tempMaterial:WallMaterial;
				if (underBitmap == null)
				{
					tempMaterial = new WallMaterial(selectedWall.length, selectedWall.height, wallBitmap, selectedWall.underBitmap);
					selectedWall.wallBitmap = wallBitmap;
				}
				else if (wallBitmap == null)
				{
					tempMaterial = new WallMaterial(selectedWall.length, selectedWall.height, selectedWall.wallBitmap, underBitmap);
					selectedWall.underBitmap = underBitmap;
				}
				selectedWall.resetMaterial(tempMaterial);
				selectedWall.setMaterialToAllFaces(selectedWall.newMaterial);
			}
		}
		
		private function isClockwise(x0:Number, y0:Number, x1:Number, y1:Number, x2:Number, y2:Number):Boolean
		{
			if (x0 * y1 + x1 * y2 + x2 * y0 - x1 * y0 - x2 * y1 - x0 * y2 <= 0)
				return true;
			else
				return false;
		}
		
		private function isSame(startPoint:Point, endPoint:Point, pPoint:Point, qPoint:Point):int
		{
			var dx:Number = endPoint.x - startPoint.x;  
			var dy:Number = endPoint.y - startPoint.y;  
			var dx1:Number = pPoint.x - startPoint.x;  
			var dy1:Number = pPoint.y - startPoint.y;  
			var dx2:Number = qPoint.x - endPoint.x;  
			var dy2:Number = qPoint.y - endPoint.y;  
			return ((dx * dy1 - dy * dx1) * (dx * dy2 - dy * dx2) > 0 ? 1 : 0);  
		}
		
		private function isIntersect(startPoint:Point, endPoint:Point, pPoint:Point, qPoint:Point):int
		{
			return (isSame(startPoint, endPoint, pPoint, qPoint)==0 && 
				　　isSame(pPoint, qPoint, startPoint, endPoint)==0) ? 1 : 0;
		}
		
		private function changeMaterial(e:MouseEvent3D):void
		{
			var object:Wall = e.target as Wall;
			if (object.selected)
			{
				unSelectWall(object);
				selectedWall = null;
			}
			else
			{
				if (selectedWall != null)
					unSelectWall(selectedWall);
				selectWall(object);
			}
		}
		
		private function changePosition(e:MouseEvent3D):void
		{
			var object:Door = e.target as Door;
			var dis:Number = Math.sqrt((camera.x - object.position.x) * (camera.x - object.position.x) + (camera.y - object.position.y) * (camera.y - object.position.y));
			if (object.isTwoSide == 1)
				Tweener.addTween(camera, {x:object.position.x + 10 * (object.position.x - camera.x) / dis,
				y:object.position.y + 10 * (object.position.y - camera.y) / dis,
				time:1});
		}
		
		private function selectWall(object:Wall):void
		{
			object.setMaterialToAllFaces(object.newMaterial);
			object.selected = true;
			selectedWall = object;
		}
		
		private function unSelectWall(object:Wall):void
		{
			object.setMaterialToAllFaces(object.rawMaterial);
			object.selected = false;
		}
		
		
		private function loadModel(x:Number, y:Number, z:Number, rotation:Number, modelURL:String, diffuseMapURL:String = null):void
		{
			var loader:URLLoader;
			var parser:ParserCollada = new ParserCollada();  
			var textureLoader:MaterialLoader = new MaterialLoader();
			loader = new URLLoader(); 
			loader.load(new URLRequest(modelURL));
			loader.addEventListener(Event.COMPLETE, onModelLoads);
			function onModelLoads(e:Event):void   
			{
				loader.removeEventListener(Event.COMPLETE,onModelLoads);
				parser.parse(new XML(e.currentTarget.data),"assets/models/");
				var mesh:Mesh;
				var staticBSP:BSP;
				for (i = 0; i<parser.objects.length; i++)
				{
					if (parser.objects[i] is Mesh)
					{
						mesh = parser.objects[i] as Mesh
						staticBSP = new BSP();
						staticBSP.createTree(mesh);
						staticBSP.splitAnalysis = true;
						container.addChild(staticBSP);
						break;
					}
				}
				var point:Point = new Point(mesh.x,mesh.y);
				var matrix:Matrix = new Matrix();
				matrix.rotate(rotation * Math.PI /180);
				point = matrix.deltaTransformPoint(point);
				staticBSP.x = x + point.x;
				staticBSP.y = y + point.y;
				staticBSP.z = z + mesh.z;
				staticBSP.scaleX = mesh.scaleX;
				staticBSP.scaleY = mesh.scaleY;
				staticBSP.scaleZ = mesh.scaleZ;
				staticBSP.rotationZ = rotation * Math.PI /180;
				if (diffuseMapURL != null)
					parser.textureMaterials[0].diffuseMapURL = diffuseMapURL;
				textureLoader.load(parser.textureMaterials);
			}
		}
		
		public function addLight():void
		{
			container.addChild(ambientLight);
			directionalLight.z = 270;
			directionalLight.rotationX = -120*Math.PI/180;
			container.addChild(directionalLight);
		}
		
		public function projectionChange():void
		{
			if (state == "freeView")
				fcamera.view.visible = !fcamera.view.visible;
		}
		
	}
}